﻿package com.net
{
	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.utils.*;

	import com.net.interfaces.INotify;

	import com.utils.Print;

	/**
	 *
	 * 只负责传输二进制数据和解决半包粘包问题
	 *
	 * 不负责包结构解析
	 *
	 * 上行包结构：两个字节的包长+一个字节的包序+两个字节命令号(模块路由+方法路由)+具体的数据
	 *
	 * 下行包结构：两个字节的包长+两个字节命令号(模块路由+方法路由)+具体的数据
	 *
	 *
	 */
	public class TcpSocket extends Socket
	{
		public static const SECURITY_ERROR : String = "securityError";

		public static const IO_ERROR : String = "ioError";

		public static const SOCKET_CLOSE : String = "close";

		public static const CONNECT_SUSSUCE : String = "connectSussuce";

		public static const ONDATA : String = "ondata";

		private var _recvBuffer : ByteArray;

		private var _tempBuffer : ByteArray;

		protected var _handler : Dictionary;

		private var order : int = 0; // 自增包序

		private const HEADLENGTH : uint = 2; // 包头长度

		public var ip : String;

		public var port : int;

		public function TcpSocket()
		{
			objectEncoding = ObjectEncoding.AMF3;
			endian = Endian.BIG_ENDIAN;

			_recvBuffer = new ByteArray();
			_tempBuffer = new ByteArray();
			_handler = new Dictionary(true);
		}

		override public function connect(ip : String, port : int) : void
		{
			ip = ip;
			port = port;
			addEventListener(Event.CONNECT, connectHandler);
			super.connect(ip, port);
		}

		/**
		 * 添加一个网络监听模块
		 * @param module
		 * @param handler
		 *
		 */
		public function addHandler(protocolId : uint, handler : INotify) : void
		{
			if (_handler[protocolId])
			{
				Print.error("添加重复协议", protocolId)
			}
			_handler[protocolId] = handler;
		}

		/**
		 *移除指定的网络监听模块
		 * @param module
		 *
		 */
		public function removeHandler(protocolId : uint) : void
		{
			_handler[protocolId] = null;
			delete _handler[protocolId];
		}

		/**
		 *身份验证
		 * @param data
		 *
		 */
		public function identity() : void
		{
			if (!connected)
			{
				return;
			}

//			if(Config.qq_client)
//				this.writeMultiByte("tgw_l7_forward\r\nHost: srv.app100666392.twsapp.com:8008\r\n\r\n", "GBK");
			this.writeUTFBytes("ABCDEFGHIJKLMN876543210");
			this.flush();
		}

		/**
		 *	发送网络数据
		 * @param module	- 模块路由
		 * @param data		- 具体数据
		 *
		 */
		public function send(module : uint, dataBytes : ByteArray) : void
		{
			if (!connected)
			{
				return;
			}
			//取对象
			var sendBytes : ByteArray = new ByteArray();
			sendBytes.writeShort(dataBytes.length); // 写入包长(不包括包头长度)
			sendBytes.writeByte(order);
			sendBytes.writeShort(module);
			sendBytes.writeBytes(dataBytes, 0, dataBytes.bytesAvailable);
			writeBytes(sendBytes);
			flush();

			if (order >= 255)
			{
				order = 0;
			}
			else
			{
				order++;
			}
		}

		private function addListener() : void
		{
			addEventListener(Event.CLOSE, closeHandler);
			addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
		}


		private function removeListener() : void
		{
			removeEventListener(Event.CLOSE, closeHandler);
			removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			removeEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
			removeEventListener(Event.CONNECT, connectHandler);
		}

		protected function closeHandler(event : Event) : void
		{
			removeListener()
			dispatchEvent(new Event(SOCKET_CLOSE));
		}

		private function connectHandler(event : Event) : void
		{
			removeEventListener(Event.CONNECT, connectHandler);
			addListener();
			dispatchEvent(new Event(CONNECT_SUSSUCE));
		}

		private function ioErrorHandler(event : IOErrorEvent) : void
		{
			trace(this, "ioErrorHandler");
			removeListener()
			dispatchEvent(new Event(IO_ERROR));

			try
			{
				close();
			}
			catch (e : Error)
			{
			}
		}

		private function securityErrorHandler(event : SecurityErrorEvent) : void
		{
			trace(this, "securityErrorHandler");
			removeListener()
			dispatchEvent(new Event(SECURITY_ERROR));

			try
			{
				close();
			}
			catch (e : Error)
			{
			}
		}

		override public function close() : void
		{
			order = 0;
			super.close();
		}


		/**
		 * 解包过程
		 * 处理半包和粘包
		 */
		private function socketDataHandler(event : ProgressEvent) : void
		{
			_tempBuffer.clear();

			if (_recvBuffer.length > 0)
			{
				_tempBuffer.writeBytes(_recvBuffer);
				_tempBuffer.position = 0
				_recvBuffer.clear();
			}
			readBytes(_tempBuffer, _tempBuffer.length, this.bytesAvailable);

			while (_tempBuffer.bytesAvailable > 0)
			{
				var packlen : int = _tempBuffer.readUnsignedShort(); // 读取包内容长度

				if (_tempBuffer.bytesAvailable >= (packlen + HEADLENGTH)) // 判断是否接收完整包，否则把半包放回缓冲等待下次一起数据到来一起读取
				{
					var module : int = _tempBuffer.readUnsignedShort(); // 读取模块号
					//取对象
					var pack : ByteArray = new ByteArray();

					if (packlen > 0)
					{
						_tempBuffer.readBytes(pack, 0, packlen);
						pack.position = 0;
					}
					parsePack(module, pack);
				}
				else
				{
					_tempBuffer.position -= HEADLENGTH; // 恢复已读的包头指针
					_recvBuffer.writeBytes(_tempBuffer, _tempBuffer.position, _tempBuffer.bytesAvailable);
					_recvBuffer.position = 0;
					break;
				}
			}
		}

		protected function parsePack(module : int, pack : ByteArray) : void
		{

		}

	}
}
